#include "FileTransfareCon.h"
#include "SrvPackage.h"

namespace Impp
{

BEGIN_EVENT_TABLE(FileTransfareCon, wxEvtHandler)
	EVT_SOCKET(ID_SOCKET_EXTERN,FileTransfareCon::onSocketEvent)
	EVT_SOCKET(ID_SOCKET_INTERN,FileTransfareCon::onSocketEvent)
END_EVENT_TABLE()
;

FileTransfareCon::FileTransfareCon() :
	client(NULL),
	clientTryIntern(NULL),
	clientTryExtern(NULL),
	buffer()
{
}

FileTransfareCon::~FileTransfareCon()
{
	if(client != NULL){
		if(client == clientTryExtern){
			client->Destroy();
			if(clientTryIntern != NULL){
				clientTryIntern->Destroy();
			}
			client = NULL;
			clientTryExtern = NULL;
			clientTryIntern = NULL;
		}
		if(client == clientTryIntern){
			client->Destroy();
			if(clientTryExtern != NULL){
				clientTryExtern->Destroy();
			}
			client = NULL;
			clientTryExtern = NULL;
			clientTryIntern = NULL;
		}
	}else{
		if(clientTryIntern != NULL){
			clientTryIntern->Destroy();
		}
		if(clientTryExtern != NULL){
			clientTryExtern->Destroy();
		}
		clientTryExtern = NULL;
		clientTryIntern = NULL;
	}
	
	
	
}

bool FileTransfareCon::connect(const FileTransfareInfo & info){
		if(clientTryExtern==NULL){
			clientTryExtern = new wxSocketClient(wxSOCKET_WAITALL);
			clientTryExtern->SetEventHandler(*this,ID_SOCKET_EXTERN);
			clientTryExtern->SetNotify(wxSOCKET_INPUT_FLAG|wxSOCKET_OUTPUT_FLAG|wxSOCKET_CONNECTION_FLAG|wxSOCKET_LOST_FLAG);
			clientTryExtern->Notify(true);
			clientTryExtern->SetTimeout(15);
			
			wxIPV4address addr;			
			addr.Hostname(ipToString(info.externIP));
			addr.Service(info.ipPort);
			clientTryExtern->Connect(addr,false);
		}
		
		if(clientTryIntern==NULL){
			clientTryIntern = new wxSocketClient(wxSOCKET_WAITALL);
			clientTryIntern->SetEventHandler(*this,ID_SOCKET_INTERN);
			clientTryIntern->SetNotify(wxSOCKET_INPUT_FLAG|wxSOCKET_OUTPUT_FLAG|wxSOCKET_CONNECTION_FLAG|wxSOCKET_LOST_FLAG);
			clientTryIntern->Notify(true);
			clientTryIntern->SetTimeout(15);
			
			wxIPV4address addr;			
			addr.Hostname(ipToString(info.ip));
			addr.Service(info.ipPort);
			clientTryIntern->Connect(addr,false);
		}
		return false;
}

bool FileTransfareCon::read(size_t lng){
	if(client != NULL){
		client->Read(((byte*)buffer.buffer)+buffer.pos,lng-buffer.pos);
		buffer.pos+=client->LastCount();
		
		if(buffer.pos < lng){
			return false;
		}
		return true;
	}
	return false;
}

FileTransfareFrame* FileTransfareCon::readFrame(){
	if(read(256)){
		SrvPackage framePack(256, buffer.buffer);
		
		FileTransfareFrame* frame = new FileTransfareFrame();
		framePack.readString(frame->magic, 4);
		
		wxLogDebug(wxT("magic: %c%c%c%c"), frame->magic[0], frame->magic[1], frame->magic[2], frame->magic[3]);
		
		if(memcmp(frame->magic,"OFT3", 4) != 0){
			wxLogDebug(wxT("Invalid Magic!"));
			delete frame;
			return NULL;
		}
		
		frame->length =framePack.readWord();
		frame->type = framePack.readWord();
		frame->cookie = framePack.readQWord();
		frame->encrypt = framePack.readWord();     
		frame->compress = framePack.readWord();        
		frame->totfiles = framePack.readWord(); 
		frame->filesleft = framePack.readWord();
		frame->totparts = framePack.readWord(); 
		frame->partsleft = framePack.readWord(); 
		frame->totsize = framePack.readDWord();      
		frame->size = framePack.readDWord();                
		frame->modtime = framePack.readDWord();      
		frame->checksum = framePack.readDWord();        
		frame->rfrcsum = framePack.readDWord();           
		frame->rfsize = framePack.readDWord();              
		frame->cretime = framePack.readDWord();            
		frame->rfcsum = framePack.readDWord();              
		frame->nrecvd = framePack.readDWord();          
		frame->recvcsum = framePack.readDWord();     
		framePack.readString(frame->idstring, 32);
		frame->flags = framePack.readWord();        
		frame->lnameoffset = framePack.readWord();      
		frame->lsizeoffset = framePack.readWord();  
		framePack.readString(frame->dummy, 69);
		framePack.readString(frame->macfileinfo, 16);
		frame->nencode = framePack.readWord(); 
		frame->nlanguage = framePack.readWord(); 
		
		//char *name;            /* 192 */
		//size_t name_length;
		
		wxLogDebug(wxT("length: %i"), frame->length);
		
		buffer.pos = 0;
		return frame;
	}
	return NULL;
}



void FileTransfareCon::onSocketEvent(wxSocketEvent & event){
	switch(event.GetSocketEvent()){
	case wxSOCKET_CONNECTION:
		{
			if(event.GetId() == ID_SOCKET_INTERN){
				if(clientTryExtern != NULL){ //we can destory the extern connection try, we are intern connected
					clientTryExtern->Destroy();
					clientTryExtern = NULL;
				}
				client = clientTryIntern; //set the right client
			}else{
				if(clientTryIntern != NULL){ //we can destroy the intern connection, we are extern connected
					clientTryIntern->Destroy();
					clientTryIntern = NULL;
				}
				client = clientTryExtern; //set the right client
			}
			
			wxLogDebug(wxT("connected!!!!!!!!!!!!!"));
		}
		break;
	case wxSOCKET_LOST:
		{
			wxLogDebug(wxT("lost!!!!!!!!!!!!!"));
		}
		break;
	case wxSOCKET_INPUT:
		{
			wxLogDebug(wxT("input!!!!!!!!!!!!!"));
			if(FileTransfareFrame* frame = readFrame()){
				wxLogDebug(wxT("Freame read!"));
				delete frame;
			}
		}
		break;
	case wxSOCKET_OUTPUT:
			wxLogDebug(wxT("output!!!!!!!!!!!!!"));
		break;
	}

}

}
